package iqq.mk.utils;

import iqq.mk.bean.Card;
import iqq.mk.bean.Compose;
import iqq.mk.bean.Gift;
import iqq.mk.bean.ThemeCard;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.script.ScriptEngine;
import javax.script.ScriptException;

import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;


public class CardInfoV3 {
	private Map<Integer, Card> cardMap; // cardId ==> Card
	private Map<Integer, Gift> giftMap; // giftId ==> Gift
	private Map<Integer, ThemeCard> themeCardMap; //themeCardId ==> ThemeCard
	private Map<Integer, Compose> composeMap;	//cardId ==> Compose
	private boolean initFinish = false;
	private static String outputPath;
	
	public static void setOutputPath(String outputPath) {
		CardInfoV3.outputPath = outputPath;
	}
	
	/**
	 * @return
	 */
	// init CardInfoV3
	private static CardInfoV3 instance = null;
	private static Date createDate;
	private static Calendar cal = new GregorianCalendar();
	public static CardInfoV3 getInstance(){
		Date nowDate = new Date();
		if(instance == null||!instance.isInitFinish()){
			instance = new CardInfoV3();
			createDate = nowDate;
		}else{
			cal.setTime(createDate);
			int last = cal.get(Calendar.DAY_OF_YEAR);
			cal.setTime(nowDate);
			int now = cal.get(Calendar.DAY_OF_YEAR);
			if(now>last){
				instance = new CardInfoV3();
				createDate = nowDate;
			}
		}
		return instance;		
	}
	/**
	 * 
	 */
	public CardInfoV3() {
		System.out.println(">>>>init CardInfoV3 >>");
		this.cardMap = new HashMap<Integer,Card>();
		this.giftMap = new HashMap<Integer,Gift>();
		this.themeCardMap = new HashMap<Integer,ThemeCard>();
		this.composeMap = new HashMap<Integer,Compose>();
		try {
			this.init(this.getCardInfoStream());
			this.initFinish = true;
			System.out.println("Init CardInfoV3 finished : "+getCardById(40));
		} catch (Exception e) {
			
		} 
	}
	/**
	 * @return
	 */
	private boolean isInitFinish() {
		// TODO Auto-generated method stub
		return this.initFinish;
	}
	/**
	 * @param in
	 * @throws JSONException
	 * @throws ScriptException
	 * @throws IOException 
	 */
	private void init(InputStream in) throws JSONException, ScriptException, IOException {		
		ScriptEngine engine = JavaScriptUtils.getScriptEngine();
		String cardinfo = IOUtils.toString(new InputStreamReader(in, "utf-8"));
		engine.eval(cardinfo);
		if(outputPath!=null){
			IOUtils.write(cardinfo,new FileOutputStream(outputPath), "utf-8");			
		}
		JSONArray themeCardArray = new JSONArray(engine.eval("theme_card_list.toJSON()").toString()),
				  cardArray = new JSONArray(engine.eval("card_list.toJSON()").toString()),
				  giftArray = new JSONArray(engine.eval("gift_list.toJSON()").toString()),
				  themeComposeArray = new JSONArray(engine.eval("theme_compose_list.toJSON()").toString());
		initCardList(cardArray);
		initGiftList(giftArray);
		initThemeCardList(themeCardArray);
		initComposeList(themeComposeArray);
	}

	/**
	 * @return
	 */
	public InputStream getCardInfoStream(){
		InputStream in = null;
		try {			
			URL postUrl = new URL("http://appimg2.qq.com/card/mk/card_info_v3.js");
			HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setRequestMethod("GET");
			connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36");
			connection.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
//			connection.addRequestProperty("Accept-Encoding", "gzip, deflate, sdch");
			connection.addRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
			connection.addRequestProperty("Cache-Control","max-age=0");
			connection.addRequestProperty("Connection", "Keep-Alive");
			connection.addRequestProperty("Host", "appimg2.qq.com");
			connection.addRequestProperty("Referer", "http://appimg2.qq.com/card/mk/card_info_v3.js");
			connection.addRequestProperty("Upgrade-Insecure-Requests","1");
			connection.addRequestProperty("Pragma", "no-cache");
			connection.addRequestProperty("DNT", "1");	
			connection.setConnectTimeout(10000);
			connection.setReadTimeout(20000);
			connection.connect();
			in = connection.getInputStream();
		} catch (Exception e) {
		}
		return in;
	}
	/**
	 * @param cardArray
	 * @throws JSONException
	 */
	private void initCardList(JSONArray cardArray) throws JSONException {
		Card card = null;		
		for(int i=0;i<cardArray.length();i++){
			card = new Card();
			JSONArray arry = cardArray.getJSONArray(i);
			card.setId(arry.getInt(0));
			card.setThemeId(arry.getInt(1));
			//card_id,theme_id,CardName,Price,Type,PickRate, Enable, version, time, item no, [mana]
			//[29,40,'鍩庡競琛楅亾',40,1,0,1,1,0,1027529,[0]],
			card.setName(arry.getString(2));
			card.setPrice(arry.getInt(3));
			card.setType(arry.getInt(4));
			card.setPickRate(arry.getInt(5));
			card.setEnable(arry.getInt(6));
			card.setVersion(arry.getInt(7));
			card.setTime(arry.getInt(8));
			card.setItemNo(arry.getInt(9));	
			int[] mana = new int[arry.getJSONArray(10).length()];
			for(int j=0;j<arry.getJSONArray(10).length();j++){
				mana[j] = arry.getJSONArray(10).getInt(j);
			}
			card.setMana(mana);
			this.cardMap.put(card.getId(), card);
		}
	}

	/**
	 * @param giftArray
	 * @throws JSONException
	 */
	private void initGiftList(JSONArray giftArray) throws JSONException {
		//gift_id, gift_type,szTYPE_ID,gift_name	
		//[24,1,'454051','modify'],
		Gift gift = null;
		for(int i=0;i<giftArray.length();i++){
			gift = new Gift();
			JSONArray arry = giftArray.getJSONArray(i);
			gift.setId(arry.getInt(0));
			gift.setType(arry.getInt(1));
			gift.setSzTYPE_ID(arry.getString(2));
			gift.setName(arry.getString(3));
			this.giftMap.put(gift.getId(),gift);
		}
	}
	/**
	 * @param themeComposeArray
	 * @throws JSONException
	 */
	private void initComposeList(JSONArray themeComposeArray) throws JSONException {
		//theme_id,state,cardtar,card1,card2,card3,costtime
		Compose compose = null;
		for(int i=0;i<themeComposeArray.length();i++){
			compose = new Compose();
			JSONArray arry = themeComposeArray.getJSONArray(i);
			compose.setThemeId(arry.getInt(0));
			compose.setState(arry.getInt(1));
			compose.setCardtar(arry.getInt(2));
			compose.setCard1(arry.getInt(3));
			compose.setCard2(arry.getInt(4));
			compose.setCard3(arry.getInt(5));
			compose.setCostTime(arry.getInt(6));
			this.composeMap.put(compose.getCardtar(),compose);
		}
	}
	/**
	 * @param themeCardArray
	 * @throws JSONException
	 */
	private void initThemeCardList(JSONArray themeCardArray) throws JSONException {
		ThemeCard themeCard = null;
		for(int i=0;i<themeCardArray.length();i++){
			themeCard = new ThemeCard();
			JSONArray arry = themeCardArray.getJSONArray(i);
			themeCard.setId(arry.getInt(0));
			themeCard.setName(arry.getString(1));
			themeCard.setDifficulty(arry.getInt(2));
			themeCard.setPublishTime(arry.getInt(3));
			themeCard.setPickRate(arry.getInt(4));
			themeCard.setEnable(arry.getInt(5));
			themeCard.setPrize(arry.getInt(6));
			themeCard.setScore(arry.getInt(7));
			themeCard.setColor(arry.getInt(8));
			
			String[] tempGift = arry.getString(9).split("\\|");
			Set<Gift> gifts = new HashSet<Gift>();
			Pattern p = Pattern.compile("\\d+");				
			for(int j=0;j<tempGift.length;j++){
				Matcher m = p.matcher(tempGift[j]);
				if(m.find()){
					gifts.add(getGiftById(Integer.valueOf(m.group())));					
				}
			}
			themeCard.setGift(gifts);			
			themeCard.setText(arry.getString(10));		
			Card[] cards = new Card[arry.getJSONArray(11).length()];
			for(int j=0;j<arry.getJSONArray(11).length();j++){
				cards[j] = getCardById(arry.getJSONArray(11).getInt(j));
				cards[j].setTheme(themeCard);
			}
			themeCard.setCards(cards);
			themeCard.setType(arry.getInt(12));
			themeCard.setVersion(arry.getInt(13));
			themeCard.setTime(arry.getInt(14));
			themeCard.setOfftime(arry.getInt(15));
			themeCard.setFlashSrcTid(arry.getInt(16));
			themeCard.setUnKnow(arry.getInt(17));//17
			this.themeCardMap.put(themeCard.getId(), themeCard);
		}
	}
	
	
	public Map<Integer, Card> getCardMap() {
		return cardMap;
	}
	public Map<Integer, Gift> getGiftMap() {
		return giftMap;
	}
	public Map<Integer, ThemeCard> getThemeCardMap() {
		return themeCardMap;
	}
	public Map<Integer, Compose> getComposeMap() {
		return composeMap;
	}
	
	public Card getCardById(int id){
		return this.cardMap.get(id);
	}
	public Gift getGiftById(int id){
		return this.giftMap.get(id);
	}
	public Gift getGiftByThemeIdAndSzType(int themeId,String szType){
		ThemeCard theme = this.themeCardMap.get(themeId);
		for(Gift gift:theme.getGift()){			
			if(gift.getSzTYPE_ID().equals(szType)){
				return gift;
			}
		}
		return null;
	}
	public ThemeCard getThemeById(int id){
		return this.themeCardMap.get(id);
	}
	public Compose getComposeByCardId(int id){
		return this.composeMap.get(id);
	}
	public Card getCardByName(String cardName) {
		for(Integer key:cardMap.keySet()){
			if(cardMap.get(key).getName().equals(cardName)){
				return cardMap.get(key);
			}
		}
		return null;
	}
	public boolean isRareCard(Integer cardId){
		Card card = getCardById(cardId);
		boolean rCode = false;
		if(card.getTheme().getType()==1||card.getTheme().getType()==5){
			rCode =  true;
		}
		return rCode;
	}
	/**
	 * @param cardId
	 * @desc count the card cost 
	 * 
	 * cost1 --  10  <= x < 40
	 * cost2 --  40  <= x < 130
	 * cost3 --  130 <= x < 320
	 * cost4 --  320 <= x < 540
	 * cost5 --  540 <= x < 10000
	 * 
	 * RareCard  cost * 5
	 */
	public int countCardCost(String cardId) {
		Card card = getCardById(Integer.valueOf(cardId));
		int cost = 1;
		int price = card.getPrice();
		if(price<40){
			cost =1;
		}else if(price<130){
			cost = 2;
		}else if(price<320){
			cost = 3;
		}else if(price<540){
			cost = 4;
		}else if(price<10000){
			cost = 5;
		}
		if(isRareCard(Integer.valueOf(cardId))){
			cost = cost * 5;
		}
		return cost;		
	}

}
